// ============================================================================
//
// Copyright (C) 2006-2007 Dengues
//
// Google Group: http://groups.google.com/group/dengues
// QQ Group: 24885404
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ============================================================================
package org.dengues.designer.core.data;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dengues.core.components.NodePropertyParameter;
import org.dengues.core.process.ICompConnection;
import org.dengues.core.process.ICompNode;
import org.dengues.core.process.ICompProcess;
import org.dengues.core.process.ICompSubProcess;
import org.dengues.core.property.EParameterFieldCategory;
import org.dengues.designer.core.data.models.AbstractCompNode;

/**
 * Qiang.Zhang.Adolf@gmail.com class global comment. Detailled comment <br/>
 * 
 * $Id: Dengues.epf Qiang.Zhang.Adolf@gmail.com 2008-1-15 qiang.zhang $
 * 
 */
public class CompDataProcess {

    private ICompProcess compProcess;

    private final List<ICompNode> dataNodes;

    private final Map<ICompNode, AbstractCompNode> nodesMap;

    /**
     * Qiang.Zhang.Adolf@gmail.com CompDataProcess constructor comment.
     * 
     * @param compProcess
     */
    public CompDataProcess(ICompProcess compProcess) {
        this();
        this.compProcess = compProcess;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "buildDataNodes".
     */
    public void buildDataNodes() {
        for (ICompNode compNode : compProcess.getCompNodes()) {
            buildDataNode(compNode);
        }
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com CompDataProcess constructor comment.
     */
    public CompDataProcess() {
        dataNodes = new ArrayList<ICompNode>();
        nodesMap = new HashMap<ICompNode, AbstractCompNode>();
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "buildDataNode".
     * 
     * @param graphicalNode
     * @return
     */
    public ICompNode buildDataNode(ICompNode graphicalNode) {
        if (nodesMap.containsKey(graphicalNode)) {
            return nodesMap.get(graphicalNode);
        }
        AbstractCompNode dataNode = new CompDataNode();
        dataNodes.add(dataNode);
        nodesMap.put(graphicalNode, dataNode);

        dataNode.setStart(graphicalNode.isStart());
        dataNode.setMetadataList(graphicalNode.getMetadataList());
        dataNode.setElementParameters(graphicalNode.getComponent().createNodeParameters(dataNode));
        initializeDataFromGraphical(dataNode, graphicalNode);
        String uniqueName = graphicalNode.getUniqueName();
        dataNode.setUniqueName(uniqueName);
        dataNode.setSubProcessStart(graphicalNode.isSubProcessStart());
        dataNode.setCompProcess(graphicalNode.getCompProcess());
        dataNode.setComponent(graphicalNode.getComponent());
        CompDataConnection dataConnec;
        for (ICompConnection connection : graphicalNode.getOutgoingConnections()) {
            dataConnec = new CompDataConnection();
            dataConnec.setMetadata(connection.getMetadata());
            dataConnec.setName(connection.getName());
            dataConnec.setSource(dataNode);
            dataNode.addOutgoingConnections(connection);
            ICompNode target = buildDataNode(connection.getTarget());
            dataConnec.setTarget(target);
            target.addIncomingConnections(connection);
        }
        return dataNode;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "initializeDataFromGraphical".
     * 
     * @param newNode
     * @param graphicalNode
     */
    private void initializeDataFromGraphical(ICompNode newNode, ICompNode graphicalNode) {
        for (NodePropertyParameter curParam : graphicalNode.getElementParameters()) {
            NodePropertyParameter dataNodeParam = newNode.getElementParameter(curParam.getName());
            if (dataNodeParam != null) {
                dataNodeParam.setValue(curParam.getValue());
                if (dataNodeParam.getFieldCategory() == EParameterFieldCategory.TABLE) {
                    dataNodeParam.setItemValues(curParam.getItemValues());
                }
            }
        }
    }

    /**
     * Getter for dataNodes.
     * 
     * @return the dataNodes
     */
    public List<ICompNode> getDataNodes() {
        return this.dataNodes;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "buildCompSubProcesses".
     * 
     * @return
     */
    public List<? extends ICompSubProcess> buildCompSubProcesses() {
        List<ICompSubProcess> compSubProcesses = new ArrayList<ICompSubProcess>();
        for (ICompNode node : getDataNodes()) {
            if (node.isSubProcessStart()) {
                compSubProcesses.add(new CompSubProcess(node));
            }
        }
        return compSubProcesses;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getRootCompNodes".
     * 
     * @return
     */
    public List<ICompNode> getRootCompNodes() {
        List<ICompNode> list = new ArrayList<ICompNode>();
        for (ICompNode compNode : getDataNodes()) {
            if (compNode.isSubProcessStart()) {
                list.add(compNode);
            }
        }
        return list;
    }

}
